#include "MyFileSystem.h"
#include <dirent.h> //文件系统库
#include <sys/stat.h>

MyFileSystem::MyFileSystem(const std::string &path)
{
    FileInfo *file = new FileInfo;
    file->name = path;
    TreeNode *rootPath = new TreeNode(file);
    rootPath->Connect(tree.GetRoot());
    ExploreDir(rootPath,file);
}

void MyFileSystem::FindByFileName(const std::string &name)
{
    FileInfo *file = new FileInfo;
    file->name = name;
    DoubleLinkList list = tree.FindByElement(file);
    for(size_t i =0;i < list.Size();i++)
    {
        TreeNode *node = (TreeNode*)*list.FindByIndex(i);
        FileInfo* path = (FileInfo*)node->GetData();
        while(node->GetParent() != nullptr&& node->GetParent() != tree.GetRoot())
        {
            FileInfo *f;
            f = (FileInfo*) node->GetParent()->GetData();
            path->name = f->name + "/" + path->name;
            node = node->GetParent();
        }
        std::cout<<path->name<<std::endl;
    }
    delete file;
}

std::string DoubleToStr(double n,int fixed = 2)//保留的位数
{
    std::string s = std::to_string(n);
    return  s.substr(0,s.find('.') + fixed + 1);
}

std::string Transform(long size)
{
    // char s[100];
    // int i =0;
    // while(size > 0)
    // {
    //     s[i] = size % 10 + '0';
    //     i++;
    //     size /= 10;
    // }

    // std::string result;
    // for(int index = i - 1; index> 0; index--)
    // {
    //     result += s[index];
    // }
    // return result;

    if(size < 1024)
        return std::to_string(size) + "B";
    else if(size <1024 *1024)
        return DoubleToStr(1.0 * size / 102)+ "KB";
    else if(size <1024 *1024*1024)
        return DoubleToStr(1.0 * size / 1024 / 1024)+ "MB";
    else 
        return DoubleToStr(1.0 * size / 1024 / 1024 / 1024)+ "GB";
}

void MyFileSystem::Print(void *p)
{
    FileInfo *file = (FileInfo *)p;
    printf("%-40s   %s\n",file->name.c_str(),file->fileSize.c_str());
}

void MyFileSystem::Free(void *p)
{
    FileInfo *file = (FileInfo *)p;
    delete file;
}

bool MyFileSystem::Compare(void *p1, void *p2)
{
    FileInfo *file1 = (FileInfo *)p1;
    FileInfo *file2 = (FileInfo *)p2;
    return (file1->name == file2->name);    
}

void MyFileSystem::ExploreDir(TreeNode *parent, FileInfo *path)
{
    DIR *dir = opendir(path->name.c_str()); // 打开一个文件夹
    if (dir == nullptr)
    {
        std::cout << "文件夹路径有误！\n";
        return;
    }
 
    dirent *d = nullptr; // 读取文件夹下的文件
    while ((d = readdir(dir)) != nullptr)
    {
        std::string dname(d->d_name);
        if (dname != "." && dname != "..")
        {
            FileInfo *file = new FileInfo;
            file->name = dname;
            TreeNode *node = new TreeNode(file);
            node->Connect(parent);
            if (d->d_type == DT_DIR)
            {
                FileInfo f;
                f.name = path->name + "/" + file->name;

                ExploreDir(node,&f);
            }
            else
            {
                struct stat s;
                stat((path->name + "/"+ file->name).c_str(),&s);//根据路劲获取文件信息
                file->fileSize = Transform(s.st_size).c_str();
            }
        }
    }
    closedir(dir); // 关闭文件夹
}
